/*
 * Copyright 2009 Colin Prinn
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

package net.recursv.motific.at.scene;

import net.recursv.motific.at.command.AtScriptCompilationException;
import net.recursv.motific.utils.Convert;
import net.recursv.motific.utils.StringList;
import net.recursv.motific.utils.WrappedException;
import net.recursv.motific.utils.files.FileSystem;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 * Created by: recursv
 * Date: 30/08/2009
 * Time: 5:01:13 PM
 */
public class ConstructManager {
    private static final Hashtable _colours = new Hashtable();
    private static final Hashtable _constructs = new Hashtable();

    public static void reset() {
        _colours.clear();
        _constructs.clear();
    }

    public static int getColor(String value) {
        if (_colours.containsKey(value))
            return ((Integer) _colours.get(value)).intValue();
        else {
            throw new AtScriptCompilationException("Unknown colour reference: " + value);
        }
    }

    public static void initialise(String rulesDirectory) {
        try {
            myInitialise(rulesDirectory);
        } catch (IOException e) {
            throw new WrappedException(e);
        }
    }

    private static void myInitialise(String rulesDirectory) throws IOException {
        StringList list = FileSystem.listFiles(rulesDirectory);
        for (int i = 0; i < list.size(); i++)
            parseRules(FileSystem.readString(list.elementAt(i)));
    }

    static void parseRules(String rules) {
        StringList list = new StringList();
        StringBuffer buf = new StringBuffer();

        boolean inConstruct = false;
        for (int index = 0; index < rules.length(); index++) {
            if (rules.charAt(index) == '{') {
                inConstruct = true;
                buf.append(rules.charAt(index));
            } else if (rules.charAt(index) == '}') {
                buf.append(rules.charAt(index));
                list.add(buf.toString());
                buf.delete(0, buf.length());
                inConstruct = false;
            } else if (rules.charAt(index) == '\n' && !inConstruct) {
                list.add(buf.toString());
                buf.delete(0, buf.length());
            } else
                buf.append(rules.charAt(index));
        }
        if (buf.length() > 0)
            list.add(buf.toString());

        parseRules(list);
    }

    static void parseRules(StringList rules) {
        for (int index = 0; index < rules.size(); index++) {
            String rule = rules.elementAt(index).trim();
            if (rule.startsWith("color") && rule.indexOf('(') != -1 && rule.indexOf(')') != -1 && rule.indexOf('=') != -1 && rule.indexOf('=') != rule.length() - 1)
                parseColor(rule);
            else if (rule.startsWith("def"))
                parseConstruct(rule);
        }
    }

    private static void parseConstruct(String rule) {
        Construct construct = new Construct(rule.substring(4, rule.indexOf('{')).trim());

        StringList list = new StringList(rule.substring(rule.indexOf('{') + 1, rule.lastIndexOf('}')), '\n');
        list.pruneEmptyStrings();

        int color = -1;
        for (int i = 0; i < list.size(); i++) {
            String req = list.elementAt(i).trim();
            if (req.startsWith("color")) {
                color = getColor(req.substring(req.indexOf('(') + 1, req.indexOf(')')));
            } else {
                SceneRequirement sceneRequirement = new SceneRequirement(req);
                sceneRequirement.setColor(color);
                construct.add(sceneRequirement);
            }
        }

        addConstruct(construct);
    }

    private static void parseColor(String rule) {
        String name = rule.substring(rule.indexOf('(') + 1, rule.indexOf(')')).trim();
        String value = rule.substring(rule.indexOf('=') + 1).trim();
        _colours.put(name, new Integer(Convert.stringToInteger(value)));
    }

    public static Construct getConstruct(String name) {
        return (Construct) _constructs.get(name);
    }

    public static void addConstruct(Construct construct) {
        _constructs.put(construct.getTitle(), construct);
    }

    public static Enumeration getConstructs() {
        return _constructs.elements();
    }
}
